#ifndef TRANSFORMERCONTENTPORTMANAGER_HPP_3
#define TRANSFORMERCONTENTPORTMANAGER_HPP_3

#include "transContentDefine.h"
#include "transContentMemory.hpp"
#include "transContentErrorCode.h"
#include "transContentITimerEvent.hpp"
#include "transContentTimer.hpp"
#include "transContentProtocol.hpp"
#include "logger.hpp"
#include "limits.h"

using namespace std;

struct portElement{
	int localPort;
	int portState;
	portClosingCallback romoveCallback;
	void* instance;	
};


/////////////////////////////////////////////////////////////////////////////////////
/// notice: 
///		1. the core method: bind and sendTo connect can use port not exist; however
///		listen, accept, receive, send, receivefrom and function method must use exist port
/// 
///		2. the get stackinfo method, must use port exist
///		3. send flag with path will work at virutal physic layer, not content layer
/////////////////////////////////////////////////////////////////////////////////////
class TransContentPortMgr : public TransContentITimerEvent{
	private:
		static TransContentPortMgr* _instance;
		int mPortCapacity;
		int mPortCount;
		int mState;

		portElement* portList;
		pthread_mutex_t mutex_port;

	public:
		static TransContentPortMgr* getInstance();
		static void releaseInstance();

		int getPortCapacity();

		int getPortCount();

		//class state
		int getState();

		//bind
		int bind(int port);

		//listen
		int listen(vroute_t vid, int count);

		//accept
		int accept(vroute_t vid, int timeout, acceptSyncCallback ascb);

		//receive
		int receive(vroute_t vid, int flag, void* buffer, int bufferLen, int timeout, recvSyncCallback rscb);

		//send
		int send(vroute_t vid, int flag, const void* buffer, int bufferLen, int timeout, sendSyncCallback sscb);

		//sendTo
		int sendTo(int localPort, const EndPoint* target, int flag, const void* buffer, int bufferLen, int timeout, sendToSyncCallback stscb);

		//receive from
		int receiveFrom(int localPort, int flag, void* buffer, int bufferLen, int timeout, receiveFromSyncCallback rfscb);

		//connect
		int connect(const EndPoint* target, int timeout, connectCallback ccb, int localPort);

		//getData
		int getData(int port, char* buffer, int len);

		int getLocalAddr(NodeAddr* nodeAddr);

		int getRemoteAddr(vroute_t vid, NodeAddr* nodeAddr);

		int tracertTarget(int port, int tracertType, const NodeAddr* target, NodeAddr* nodeList, int nodeCount, int timeout, tarcertTargetCallback ttcb);

		int queryTarget(int port, int type, int valueLength, void* value, deviceInfo* result, int timeout, queryTargetCallback qtcb);

		int targetReachable(int port, const NodeAddr* target, int timeout, targetReachAbleCallback tracb);

		int setFixedNodeList(const NodeAddr* target, const NodeAddr* nodeList, int nodeCount);

		int getVroutePort(vroute_t vid);

		int getErrorInfo(int errno_num, char* buffer, int bufferLen);

		int isPortAlreadyExist(int port);

		void onTimer();

		int getAPort();

		int registPort(int port, int timeout, registPortCallback rgcb);

		int setPortClosingCallback(int port, portClosingCallback pccb);
	
		int setPortClosingCallbackVid(vroute_t vid, portClosingCallback pccb);

		portClosingCallback getPortClosingCallback(int port);

		portClosingCallback getPortClosingCallbackVid(vroute_t vid);

		void restart();

		void dispatcher(char* buffer, int index);

		int getAPortLocal();

		int closePort(int port);

		int closeVid(vroute_t vid);
	private:
		TransContentPortMgr();
	
		virtual ~TransContentPortMgr();

		int isPortExist(int port, int portState = PORT_STATE_ERROR);
	
		int increasePortRecordSpace();

		/// remote port record by port	
		int removePortRecord(int port, int index=-1);
		int changeRecordState(int index, int oldState, int newState, void* newInstance);

		int messageToState(int MessageCode);
		
		void heartBeatResponse(char* buffer, int index);
		
		void DispatchWithPort(char* buffer, int index);

		int AddPortRecord(const portElement* element);

		/// add the port as registed record
		int addPortRecordAsRegist(int port);

		void destroyAllPortRecord();

		/// check the port's state can be changed to function call
		int canPortStateChangedToFunctionRelate(int port);

		/// check the port's state can be changed to record
		int canChangePortStateToRecord(int port);

		/// check the port's state can be changed to connecting
		int canChangePortStateToConnect(int port);

		/// the port alredy and state not be registed, check it's state can changed to registed
		int canChagnePortStateToRegisted(int port);

		void closePortToStack(int port);

		/// regist a port to stack
		int registPortInner(int port, int portType, int returnType);

		/// action for the result
		int analysePortResult(int result, int bufferIndex, int recordIndex);

		/// port list deal the maincode
		int dispatcherForPortList(char* content, int index);

		/// call instance rsponse to deal the main message
		int dispatcherForPortInstance(char* content, int index);

		/// not support mainCode
		int dispatcherForException(char* content, int index );

		/// create a steam instance
		int createPortStreamInstance(const ConnectPeer* peer, int remoteBufferSize, int remoteStreamStart, int acceptPort = -1);

		int initClient();
	private:
		/// set the port manager copy constructor and assigment to private, so that can not copy and assigment
		TransContentPortMgr(const TransContentPortMgr& src);
		TransContentPortMgr operator=(const TransContentPortMgr& rhs);
};
#endif //TRANSFORMERCONTENTPORTMANAGER_HPP_3
